package gamemodels;

import gamecomponents.graphic.BlitData;
import gamecomponents.graphic.Blitable;
import gamecomponents.graphic.TextureHelper;
import gamecomponents.menu.MenuButton;
import gamecomponents.menu.MenuImage;
import gamecomponents.settings.GameSettings;
import input.InputManager;

import java.awt.event.KeyEvent;
import java.util.LinkedList;
import java.util.List;
import java.util.Observable;

import maze.MazeSize;

import com.threed.jpct.SimpleVector;

/**
 * A Model representing the New Game Sub menu
 * @author Team Deer
 * 
 */
public class NewGameMenuModel extends Observable implements IGameModel {

	private static NewGameMenuModel singletonInstance;
	private boolean requestExit;
	private final SimpleVector screenSize;
	private IGameModel nextModel;

	private final List<Blitable> components;
	private final MenuImage backgroundImage;
	private final MenuButton smallMazeButton;
	private final MenuButton mediumMazeButton;
	private final MenuButton largeMazeButton;
	private final MenuButton backButton;

	// Constructor and singleton getter
	
	/**
	 *  Constructs a NewGameMenuModel
	 */
	private NewGameMenuModel() {
		this.screenSize = GameSettings.SCREEN_SIZE;

		this.components = new LinkedList<Blitable>();

		this.backgroundImage = new MenuImage(
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\menubackground.png"),
				0, 0, (int) this.screenSize.x, (int) this.screenSize.y, 255);
		this.components.add(this.backgroundImage);

		this.smallMazeButton = new MenuButton(
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\smallMazeActive.png"),
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\smallMazeInactive.png"),
				(int) this.screenSize.x / 8, (int) this.screenSize.y / 2, 634,
				56, 255);
		this.components.add(this.smallMazeButton);

		this.mediumMazeButton = new MenuButton(
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\mediumMazeActive.png"),
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\mediumMazeInactive.png"),
				(int) (this.screenSize.x / 8),
				(int) (this.screenSize.y / 2 + 75), 709, 56, 255);
		this.components.add(this.mediumMazeButton);

		this.largeMazeButton = new MenuButton(
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\largeMazeActive.png"),
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\largeMazeInactive.png"),
				(int) this.screenSize.x / 8, (int) this.screenSize.y / 2 + 150,
				625, 56, 255);
		this.components.add(this.largeMazeButton);

		this.backButton = new MenuButton(
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\backActive.png"),
				TextureHelper
						.loadTexture("Content\\Sprites\\Menu\\backInactive.png"),
				(int) this.screenSize.x / 8, (int) this.screenSize.y / 2 + 225,
				147, 48, 255);
		this.components.add(this.backButton);
		this.setChanged();
	}

	/**
	 * @return the singleton instance.
	 */
	public static NewGameMenuModel getInstance() {
		if (singletonInstance == null) {
			singletonInstance = new NewGameMenuModel();
		}
		return singletonInstance;
	}

	// Update
	
	@Override
	public void reset() {
		this.requestExit = false;
		this.nextModel = null;
	}

	@Override
	public boolean isRunning() {
		return !this.requestExit;
	}

	@Override
	public void update(final InputManager inputManager) {
		if ((inputManager.getKeyboardState().isKeyPressed(KeyEvent.VK_ESCAPE) &&
				inputManager.getKeyboardState().getPreviousKeyboardState().isKeyUp(KeyEvent.VK_ESCAPE))
				|| (inputManager.getKeyboardState().isKeyPressed(KeyEvent.VK_BACK_SPACE) &&
						inputManager.getKeyboardState().getPreviousKeyboardState().isKeyUp(KeyEvent.VK_BACK_SPACE))) {
			this.changeModel(MainMenuModel.getInstance());
		}

		updateButtons(inputManager);
		if (this.buttonsHasChanged()) {
			super.setChanged();
		}

		super.notifyObservers();

	}

	private void updateButtons(final InputManager inputManager) {
		this.smallMazeButton.update(inputManager);
		this.mediumMazeButton.update(inputManager);
		this.largeMazeButton.update(inputManager);
		this.backButton.update(inputManager);
		if (inputManager.mouseIsClicked()) {
			if (this.smallMazeButton.pointIsOver(inputManager
					.getMousePosition())) {
				SinglePlayerModel.getInstance().createNewGame(MazeSize.SMALL, false);
				this.changeModel(SinglePlayerModel.getInstance());
			}
			if (this.mediumMazeButton.pointIsOver(inputManager
					.getMousePosition())) {
				SinglePlayerModel.getInstance().createNewGame(MazeSize.MEDIUM, false);
				this.changeModel(SinglePlayerModel.getInstance());
			}
			if (this.largeMazeButton.pointIsOver(inputManager
					.getMousePosition())) {
				SinglePlayerModel.getInstance().createNewGame(MazeSize.LARGE, false);
				this.changeModel(SinglePlayerModel.getInstance());
			}
			if (this.backButton.pointIsOver(inputManager.getMousePosition())) {
				this.changeModel(MainMenuModel.getInstance());
			}
		}
	}

	private boolean buttonsHasChanged() {
		return this.smallMazeButton.hasChanged()
				|| this.mediumMazeButton.hasChanged()
				|| this.largeMazeButton.hasChanged()
				|| this.backButton.hasChanged();
	}

	private void changeModel(final IGameModel model) {
		this.nextModel = model;
	}

	@Override
	public IGameModel getNextModel() {
		return this.nextModel;
	}

	// Viewhelp
	
	@Override
	public List<BlitData> getBlitData() {
		final List<BlitData> list = new LinkedList<BlitData>();

		for (final Blitable data : this.components) {
			list.add(new BlitData(
					data.getTexture(), // texture
					0 /* srcX */, 0 /* srcY */, data.getPosition().x /* destX */,
					data.getPosition().y /* destY */,
					data.getSrcWidth() /* sourceWidth */,
					data.getSrcHeight() /* sourceHeight */,
					data.getWidth() /* destWidth */,
					data.getHeight() /* destHeight */, 255 /* transValue */,
					false /* additive */, null)); /* addColor */
		}

		return list;
	}

}
